package cn.bingoo.leaksuspects;

import java.io.File;
import java.text.MessageFormat;
import java.util.List;
import java.util.regex.Pattern;

import javax.swing.JCheckBox;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import org.dom4j.CDATA;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.Text;
import org.dom4j.io.SAXReader;

import cn.bingoo.swing.utils.Swings;

import com.esotericsoftware.wildcard.Paths;
import com.google.common.base.Charsets;
import com.google.common.base.Strings;
import com.google.common.io.Files;

public class LeakSuspects {

    static Pattern compile = Pattern.compile("#.+#", Pattern.DOTALL);

    private JTextField countField = null;

    private int scanFileCount = 0;
    private int suspectsFileCount = 0;
    private int suspectsSqlCount = 0;

    public void workTree(JTextArea textArea, JCheckBox chckbxScrollLock, String... pathNames) throws Exception {
        Paths paths = new Paths();
        for (String pathName : pathNames) {
            paths.glob(pathName,
                    "**/*.xml", "!**/.svn/**", "!**/classes/**",
                    "!*/target/**", "!**/pom.xml", "!*/.settings/**");
        }

        List<File> files = paths.getFiles();
        for (File file : files) {
            scanFileCount++;
            String text = Files.toString(file, Charsets.UTF_8);
            if (text.indexOf("<sqlMap") < 0 || text.indexOf("<select") < 0) {
                continue;
            }
            findFromIbatisXml(textArea, chckbxScrollLock, file);
        }
    }

    //    public static void main(String[] args) throws DocumentException {
    //        //        String fileName = "E:\\\\Workspaces\\\\ess_shop\\\\admin-service\\\\src\\\\main\\\\resources\\\\com\\\\ailk\\\\mall\\\\sell\\\\order\\\\delivery\\\\OrderDeliverySQL.xml";
    //        String fileName = "E:\\Workspaces\\ess_shop\\cust-service\\src\\main\\resources\\com\\ailk\\cac\\sql\\custmgr\\EcsCustInfoQuerySQL.xml";
    //        findFromIbatisXml(fileName);
    //    }

    //    public static void findFromIbatisXml(String fileName) throws DocumentException {
    //        findFromIbatisXml(new File(fileName));
    //    }

    @SuppressWarnings("unchecked")
    public void findFromIbatisXml(JTextArea textArea, JCheckBox chckbxScrollLock, File file) throws Exception {
        Swings.appendText(textArea, chckbxScrollLock, file + "\r\n", null);
        Document doc = read(file);
        Element root = doc.getRootElement();
        List<Element> sqlElements = root.elements("sql");
        List<Element> elements = root.elements("select");
        boolean hasSuspects = false;
        for (Element select : elements) {
            StringBuilder sql = new StringBuilder();
            for (int i = 0; i < select.nodeCount(); ++i) {
                Node object = select.node(i);
                if (object instanceof Text) {
                    Text str = (Text) object;
                    sql.append(str.getText());
                }
                else if (object instanceof Element) {
                    Element element = (Element) object;
                    if (element.getName().equals("include")) {
                        for (Element sqle : sqlElements) {
                            if (element.attributeValue("refid").equals(sqle.attributeValue("id"))) {
                                sql.append(sqle.getText());
                                break;
                            }
                        }
                    }
                }
                else if (object instanceof CDATA) {
                    CDATA cdata = (CDATA) object;
                    sql.append(cdata.getText());
                }
            }
            String sql2 = sql.toString().trim();
            if (compile.matcher(sql2).find()) {
                continue;
            }
            if (sql2.toUpperCase().endsWith("FROM DUAL")) {
                continue;
            }
            hasSuspects = true;
            suspectsSqlCount++;
            String x = Strings.repeat("-", 10) + select.attributeValue("id") + Strings.repeat("-", 10);
            Swings.appendText(textArea, chckbxScrollLock, x + "\r\n", null);
            Swings.appendText(textArea, chckbxScrollLock, sql2 + "\r\n", null);
        }
        if (hasSuspects) {
            suspectsFileCount++;
        }

        countField.setText(MessageFormat.format("Scan Files : {0}, Suspected Files: {1}, Suspected Sqls: {2}",
                scanFileCount, suspectsFileCount, suspectsSqlCount));
    }

    public static Document read(File file) throws DocumentException {
        SAXReader reader = new SAXReader();
        Document document = reader.read(file);
        return document;
    }

    public static Document read(String fileName) throws DocumentException {
        SAXReader reader = new SAXReader();
        Document document = reader.read(new File(fileName));
        return document;
    }

    public JTextField getCountField() {
        return countField;
    }

    public void setCountField(JTextField countField) {
        this.countField = countField;
    }

}
